home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
United Public Domain Gold 4
/
United Public Domain Gold 4.iso
/
fredfish
/
ff.0355.dms
/
ff.0355.adf
/
LoadImage
/
LoadImage.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-06-12
|
49KB
|
2,308 lines
/* $Revision Header * Header built automatically - do not edit! *************
*
* (C) Copyright 1990 by MXM
*
* Name .....: LoadImage.c
* Created ..: Saturday 23-Sep-90 12:30
* Revision .: 11
*
* Date Author Comment
* ========= ======== ====================
* 11-May-90 Olsen New routines
* 01-May-90 Olsen Rework for Aztec 5.0 release
* 23-Sep-89 Olsen Created this file!
*
* $Revision Header ********************************************************/
/* Arp user interface stuff. */
char *CLI_Template = "INFO/S,NOMODE/S,LACE/S,CYCLE/S,Files,,,,,,";
char *CLI_Help = "\nUsage: LoadImage [INFO] [NOMODE] [LACE] [CYCLE] Files1 ... FileN\n\n NOMODE and LACE are mutually exclusive.\n";
/* Argument vector offsets. */
#define ARG_INFO 1
#define ARG_NOMODE 2
#define ARG_LACE 3
#define ARG_CYCLE 4
#define ARG_FILES 5
/* The cycling code needs this to be defined externally. */
CRange CycleRange[6];
/* Some more fontdata for the Requester soon to come. */
struct TextAttr StandardFont[3] =
{
{(UBYTE *)"topaz.font",8,FS_NORMAL ,FPF_ROMFONT},
{(UBYTE *)"topaz.font",8,FSF_BOLD ,FPF_ROMFONT},
{(UBYTE *)"topaz.font",8,FSF_ITALIC,FPF_ROMFONT}
};
/* Menu text definitions. */
struct IntuiText MenuIntTxt[10] =
{
{0,0,0,2,1,&StandardFont[0],(UBYTE *)"About LoadImage...", NULL},
{0,0,0,0,0,&StandardFont[1],(UBYTE *)"________________________",NULL},
{0,0,0,2,1,&StandardFont[0],(UBYTE *)"Title bar", NULL},
{0,0,0,2,1,&StandardFont[0],(UBYTE *)"Cycling", NULL},
{0,0,0,0,0,&StandardFont[1],(UBYTE *)"________________________",NULL},
{0,0,0,2,1,&StandardFont[0],(UBYTE *)"Print Standard", NULL},
{0,0,0,2,1,&StandardFont[0],(UBYTE *)" Enlarged", NULL},
{0,0,0,0,0,&StandardFont[1],(UBYTE *)"________________________",NULL},
{0,0,0,2,1,&StandardFont[0],(UBYTE *)"Next Image", NULL},
{0,0,0,2,1,&StandardFont[0],(UBYTE *)"Quit LoadImage", NULL}
};
/* A chain of menu items. */
struct MenuItem MenuItem[10] =
{
{&MenuItem[1], 1, 0,196,10, 86,0,(APTR)&MenuIntTxt[0],NULL,'?',NULL,NULL},
{&MenuItem[2], 3, 4,192, 8,210,0,(APTR)&MenuIntTxt[1],NULL, 0,NULL,NULL},
{&MenuItem[3], 1,13,196,10, 86,0,(APTR)&MenuIntTxt[2],NULL,'T',NULL,NULL},
{&MenuItem[4], 1,23,196,10, 86,0,(APTR)&MenuIntTxt[3],NULL,'C',NULL,NULL},
{&MenuItem[5], 3,27,192, 8,210,0,(APTR)&MenuIntTxt[4],NULL, 0,NULL,NULL},
{&MenuItem[6], 1,36,196,10, 86,0,(APTR)&MenuIntTxt[5],NULL,'S',NULL,NULL},
{&MenuItem[7], 1,46,196,10, 86,0,(APTR)&MenuIntTxt[6],NULL,'E',NULL,NULL},
{&MenuItem[8], 3,50,192, 8,210,0,(APTR)&MenuIntTxt[7],NULL, 0,NULL,NULL},
{&MenuItem[9], 1,59,196,10, 86,0,(APTR)&MenuIntTxt[8],NULL,'N',NULL,NULL},
{NULL, 1,69,196,10, 86,0,(APTR)&MenuIntTxt[9],NULL,'Q',NULL,NULL}
};
/* Our only menu. */
struct Menu Menu = { NULL,1,0,120,0,257,"LoadImage 1.11",&MenuItem[0] };
/* Requester text definitions. */
struct IntuiText ReqIntTxt[] =
{
{0,0,0, 76, 4,&StandardFont[0],(UBYTE *)"Understood", NULL},
{0,0,0, 94, 6,&StandardFont[1],(UBYTE *)"LoadImage 1.11", &ReqIntTxt[2]},
{0,0,0, 34, 18,&StandardFont[0],(UBYTE *)"Was written by Olaf 'Olsen'", &ReqIntTxt[3]},
{0,0,0, 34, 26,&StandardFont[0],(UBYTE *)"Barthel of MXM. This version", &ReqIntTxt[4]},
{0,0,0, 34, 34,&StandardFont[0],(UBYTE *)"supports EHB & HAM pictures,", &ReqIntTxt[5]},
{0,0,0, 34, 42,&StandardFont[0],(UBYTE *)"will also take care of", &ReqIntTxt[6]},
{0,0,0, 34, 50,&StandardFont[0],(UBYTE *)"oversized pictures which", &ReqIntTxt[7]},
{0,0,0, 34, 58,&StandardFont[0],(UBYTE *)"require 1M of chip ram and", &ReqIntTxt[8]},
{0,0,0, 46, 66,&StandardFont[0],(UBYTE *)"features an Arp interface.", &ReqIntTxt[9]},
{0,0,0, 34, 82,&StandardFont[0],(UBYTE *)"Press the left mouse button", &ReqIntTxt[10]},
{0,0,0, 34, 90,&StandardFont[0],(UBYTE *)"and move the pointer towards", &ReqIntTxt[11]},
{0,0,0, 34, 98,&StandardFont[0],(UBYTE *)"the borders of the screen to", &ReqIntTxt[12]},
{0,0,0, 34,106,&StandardFont[0],(UBYTE *)"scroll around in overscanned", &ReqIntTxt[13]},
{0,0,0,122,114,&StandardFont[0],(UBYTE *)"images.", &ReqIntTxt[14]},
{0,0,0, 58,130,&StandardFont[2],(UBYTE *)"© Copyright 1990 by MXM", NULL}
};
/* Requester border coordinates. */
SHORT ReqBrdDat[] =
{
-3,-2,234,-2,234, 17,-3, 17,-3,-2,
-6,-4,237,-4,237, 19,-6, 19,-6,-4,
0, 0,293, 0,293,172, 0,172, 0, 0,
0, 0,295, 0,295,172, 0,172, 0, 0
};
/* Requester border definitions. */
struct Border ReqBrd[] =
{
{0,0,0,0,0,5,&ReqBrdDat[ 0],&ReqBrd[1]},
{0,0,0,0,0,5,&ReqBrdDat[10],NULL},
{3,1,0,0,0,5,&ReqBrdDat[20],&ReqBrd[3]},
{2,1,0,0,0,5,&ReqBrdDat[30],NULL}
};
/* The only gadget employed by the Requester. */
struct Gadget ReqGad = {NULL,34,149,232,16,0,3,4097,(APTR)&ReqBrd[0],NULL,&ReqIntTxt[0],NULL,NULL,0,NULL};
/* Our only Requester. */
struct Requester Req;
/* Yes... we will open a CUSTOMBITMAP screen. */
struct BitMap ScreenMap;
/* If the picture is smaller than the screen. */
struct BitMap TinyBitMap;
/* Must be defined externally since three routines need it.
* There could have been an easier way to do this, but it was
* me who programmed it and not a "reentrant-code-fanatic".
*/
BitMapHeader InfoHeader;
/* Empty colour information. */
UWORD BlackIsBlack[32] =
{
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0
};
/* Wait and see what this will be! */
struct NewScreen NewScreen =
{
0,0,0,0,0, /* Gets filled in later. */
0,1, /* Pens. */
NULL, /* ViewModes, get filled in later. */
CUSTOMSCREEN | SCREENBEHIND | CUSTOMBITMAP,
&StandardFont[0], /* Just insure that the menu looks cute. */
(STRPTR)"LoadImage 1.11", /* Some title text. */
NULL, /* No gagdets. */
&ScreenMap /* Custom bitmap! */
};
/* What do we need this window for? We've got a menu and
* screens don't like menus very much...
*/
struct NewWindow NewWindow =
{
0,0, /* These get filled in later. */
0,0,
0,1, /* Pens. */
GADGETUP | MOUSEBUTTONS | MENUPICK | MENUVERIFY | MOUSEMOVE | RAWKEY, /* We want to know about this. */
BACKDROP | BORDERLESS | RMBTRAP, /* This is how it should look like. */
(struct Gadget *)NULL, /* Don't need a gadget. */
(struct Image *)NULL, /* Don't need a checkmark either. */
(STRPTR)NULL, /* Don't need a title. */
(struct Screen *)NULL, /* This gets filled in later. */
(struct BitMap *)NULL, /* Don't need it, really. */
0,0, /* Minimum dimensions. */
0,0, /* Maximum dimensions. */
CUSTOMSCREEN /* No Workbench, this is MY window. */
};
/* External symbols the linker wants. */
extern struct IntuitionBase *IntuitionBase;
extern struct GfxBase *GfxBase;
extern struct ExecBase *SysBase;
struct Screen *Screen;
struct Window *Window;
/* Check for ^C signal. */
#define BreakCheck() (SetSignal(0,0) & SIGBREAKF_CTRL_C)
/* Macro expressions to set the pointer for our window. */
#define SetPoint(wind) SetPointer(wind,PointData,7,16,-4,-3)
#define SetSnooze(wind) SetPointer(wind,Snooze,22,16,-9,-13)
#define SetSize(wind) SetPointer(wind,SizeData,13,16,-4,-3)
/* Sprite dump for the pointer image. */
USHORT PointData[(2 + 7) * 2] =
{
0x0000,0x0000,
0x0000,0x1000,
0x1000,0x0000,
0x1000,0x1000,
0x6C00,0xAA00,
0x1000,0x1000,
0x1000,0x0000,
0x0000,0x1000,
0x0000,0x0000
};
/* Sprite dump for the Workbench balloon. */
USHORT Snooze[(2 + 22) * 2] =
{
0x0000,0x0000,
0x0700,0x0000,
0x0FA0,0x0700,
0x3FF0,0x0FA0,
0x70F8,0x3FF0,
0x7DFC,0x3FF8,
0xFBFC,0x7FF8,
0x70FC,0x3FF8,
0x7FFE,0x3FFC,
0x7F0E,0x3FFC,
0x3FDF,0x1FFE,
0x7FBE,0x3FFC,
0x3F0E,0x1FFC,
0x1FFC,0x07F8,
0x07F8,0x01E0,
0x01E0,0x0080,
0x07C0,0x0340,
0x0FE0,0x07C0,
0x0740,0x0200,
0x0000,0x0000,
0x0070,0x0020,
0x0078,0x0038,
0x0038,0x0010,
0x0000,0x0000
};
USHORT SizeData[(2 + 13) * 2] =
{
0x0000,0x0000,
0x0000,0x1000,
0x1000,0x0000,
0x1000,0x1000,
0x6C00,0xAA00,
0x1000,0x1000,
0x1000,0x0000,
0x0000,0x1000,
0x0000,0x0000,
0x0D77,0x0D77,
0x1114,0x1114,
0x1D27,0x1D27,
0x0544,0x0544,
0x1977,0x1977,
0x0000,0x0000
};
/* This is where the colours go when the About item is
* selected.
*/
UWORD PrefColours[32];
struct Preferences StandardPrefs;
/* MakeID(IDString) :
*
* Transforms a string into a chunk ID. How can we do this
* in a macro expression? Just don't know.
*/
ULONG
MakeID(char *IDString)
{
ULONG LongID;
LongID = (IDString[0] << 24) | (IDString[1] << 16) | (IDString[2] << 8) | (IDString[3]);
return(LongID);
}
/* FindChunk(ChunkName,FilePointer) :
*
* Will try to find a chunk ID somewhere in the
* file. If it doesn't find any it returns FALSE.
* This routine was somewhat inspired by the
* Chunk-reader to be found on the disk distributed
* along with the FutureSound sound sampling hardware.
* Some months later I through the 'crap' out. Instead
* of years this will take you only some moments to
* load now.
*/
LONG
FindChunk(char *ChunkName,FILE *FilePointer)
{
IFF_Chunk Chunk;
LONG OldPosition,FormType,WeWant;
/* Set up the chunk type. */
WeWant = MakeID(ChunkName);
/* Remember the initial file position. */
OldPosition = ftell(FilePointer);
/* Reset the form type. */
FormType = 0;
for(;;)
{
/* Try to read the chunk. */
if(fread(&Chunk,sizeof(Chunk),1,FilePointer) != 1)
{
/* If it went wrong, reset the
* file position.
*/
fseek(FilePointer,OldPosition,0);
return(0);
}
/* If this is supposed to be a FORM chunk,
* try to figure out the form type.
*/
if(OldPosition == 0 && FormType == 0 && Chunk . IFF_Type == MakeID("FORM"))
{
fread(&FormType,sizeof(LONG),1,FilePointer);
/* Is it the type we want? */
if(FormType == WeWant)
return(Chunk . IFF_Length);
continue;
}
/* Is this what we want? */
if(Chunk . IFF_Type == WeWant)
return(Chunk . IFF_Length);
/* Else, skip the length information. */
fseek(FilePointer,Chunk . IFF_Length,1);
}
}
/* LoadHeader(FileName,BMHeader) :
*
* Does two jobs for us: Initializes the BitMapHeader
* and tries to figure out the Amiga ViewModes this
* file needs. Returns -1 on failure, not NULL.
*/
LONG
LoadHeader(char *FileName,BitMapHeader *BMHeader)
{
FILE *ImageFile;
LONG ViewModes = NULL;
/* No such file? */
if(!(ImageFile = fopen(FileName,"r")))
return(-1);
/* No BMHD-Chunk? */
if(!FindChunk("BMHD",ImageFile))
{
fclose(ImageFile);
return(-1);
}
/* Read the header. */
fread(BMHeader,sizeof(BitMapHeader),1,ImageFile);
/* Strange values, probably not a picture but a
* "mistake", or even a CMAP.
*/
if(BMHeader -> nPlanes < 1 || BMHeader -> nPlanes > 8)
{
fclose(ImageFile);
return(-1);
}
/* If we don't find a CAMG chunk in the file
* we will have to guess the right
* ViewModes. This line takes care of the
* interlaced display mode.
*/
if(BMHeader -> pageHeight > GfxBase -> NormalDisplayRows)
ViewModes |= LACE;
/* Could it be HIRES? */
if(BMHeader -> pageWidth >= 640)
ViewModes |= HIRES;
/* It is still much more likely to encounter a
* HAM picture than an EHB picture. If we are
* wrong with this assumption, the CAMG chunk
* will tell us (hope so).
*/
if(BMHeader -> nPlanes == 6)
ViewModes |= HAM;
/* Hello out there, got any CAMG chunk? */
if(!FindChunk("CAMG",ImageFile))
{
fclose(ImageFile);
return(ViewModes);
}
/* Read it then. */
fread(&ViewModes,sizeof(LONG),1,ImageFile);
/* Mask out all unwanted bits (thanks, Carolyn!). */
ViewModes &= (~(SPRITES | VP_HIDE | GENLOCK_AUDIO | GENLOCK_VIDEO) | 0xFFFF);
/* Finish it. */
fclose(ImageFile);
return(ViewModes);
}
/* LoadCMAP(FileName,ColourMap,MaxCol,BMHeader) :
*
* Will load an unsigned word array with the
* colours to be found in the CMAP chunk.
*/
LONG
LoadCMAP(char *FileName,UWORD *ColourMap,LONG MaxCol,BitMapHeader *BMHeader)
{
LONG i;
FILE *ColFile;
LONG R,G,B;
/* Are you there? */
if(!(ColFile = fopen(FileName,"r")))
return(0);
/* Black 'n white or colour TV? */
if(!FindChunk("CMAP",ColFile))
{
fclose(ColFile);
return(0);
}
/* Correct it before the reader believes it! */
if(MaxCol < 2)
MaxCol = 1 << BMHeader -> nPlanes;
/* A bit too large, innit? */
if(MaxCol > 32)
MaxCol = 32;
/* Read those colours. */
for(i = 0 ; i < MaxCol ; i++)
{
R = fgetc(ColFile) >> 4;
G = fgetc(ColFile) >> 4;
B = fgetc(ColFile) >> 4;
/* The transformation. */
ColourMap[i] = (R << 8) | (G << 4) | (B);
}
/* Finish it. */
fclose(ColFile);
return(MaxCol);
}
/* LoadRaster(FileName,BitPlanes,BMHeader) :
*
* Will decompress the interleaved bitmap data
* into a set of bitplanes.
*/
UBYTE
LoadRaster(char *FileName,PLANEPTR *BitPlanes,BitMapHeader *BMHeader)
{
LONG i,j,k;
UBYTE Value,SoFar,Compr,Depth;
BYTE ChkVal;
LONG Height,Width;
PLANEPTR Planes[9]; /* 9 for possible bitmask. */
FILE *PicFile;
BYTE *AuxBuff; /* Decompress in memory buffer. */
BYTE *AuxBuff2;
LONG AuxLength;
/* Clear the planes. */
for(i = 0 ; i < 9 ; i++)
Planes[i] = NULL;
/* Set up the working copies. */
Width = LineBytes(BMHeader -> w);
Height = BMHeader -> h;
Depth = BMHeader -> nPlanes;
Compr = BMHeader -> compression;
/* Is there something wrong in paradise? */
if(Compr > 1 || !BitPlanes)
return(FALSE);
/* Can we read it, please? */
if(!(PicFile = fopen(FileName,"r")))
return(FALSE);
/* No BODY? What is this? */
if(!(AuxLength = FindChunk("BODY",PicFile)))
{
fclose(PicFile);
return(FALSE);
}
/* Copy the bitmap pointers since their
* contents will get changed.
*/
for(i = 0 ; i < Depth ; i++)
Planes[i] = BitPlanes[i];
/* Very well, nobody told me that DPaint and Aegis Images
* are allowed to save their own home-brewn BODY chunks
* if the transparent colour is nonzero or the
* stencil/behind function is used. In this case the
* interleaved plane data is immediately followed by
* a bitmask which is to clear out all unwanted pixels
* after the image is drawn. To support this attitude
* we increment the depth of the image to give the
* reader access to a blank pointer the bitmask will
* be sent to.
*/
if(BMHeader -> masking == 1)
Depth++;
/* If we can allocate the memory buffer, we will
* decompress the image in memory rather than
* while reading it from disk.
*/
if(AuxBuff = (BYTE *)AllocMem(AuxLength,MEMF_PUBLIC))
{
/* Read the data. */
fread(AuxBuff,AuxLength,1,PicFile);
/* Remember the buffer address. */
AuxBuff2 = AuxBuff;
/* No compression? */
if(Compr == 0)
{
for(k = 0 ; k < Height ; k++)
{
for(j = 0 ; j < Depth ; j++)
{
if(Planes[j])
{
CopyMem(AuxBuff,Planes[j],Width);
Planes[j] += Width;
}
AuxBuff += Width;
}
}
}
/* ByteRun compression? */
if(Compr == 1)
{
for(k = 0 ; k < Height ; k++)
{
for(j = 0 ; j < Depth ; j++)
{
for(SoFar = 0 ; SoFar < Width ; )
{
ChkVal = *AuxBuff;
AuxBuff++;
if(ChkVal > 0)
{
if(Planes[j])
{
CopyMem(AuxBuff,Planes[j],ChkVal + 1);
Planes[j] += ChkVal + 1;
}
AuxBuff += ChkVal + 1;
SoFar += ChkVal + 1;
}
else
{
if(ChkVal != -128)
{
Value = *AuxBuff;
AuxBuff++;
for(i = 0 ; i <= -ChkVal ; i++)
{
if(Planes[j])
{
*Planes[j] = Value;
Planes[j]++;
}
SoFar++;
}
}
}
}
}
}
}
/* Free the auxilary buffer. */
FreeMem(AuxBuff2,AuxLength);
goto Quit;
}
/* No compression, take the data as is. */
if(Compr == 0)
{
for(k = 0 ; k < Height ; k++)
{
for(j = 0 ; j < Depth ; j++)
{
if(Planes[j])
{
fread(Planes[j],Width,1,PicFile);
Planes[j] += Width;
}
else
fseek(PicFile,Width,1);
}
}
}
/* ByteRun1 compression, efficient but tricky. */
if(Compr == 1)
{
for(k = 0 ; k < Height ; k++)
{
for(j = 0 ; j < Depth ; j++)
{
for(SoFar = 0 ; SoFar < Width ; )
{
ChkVal = fgetc(PicFile);
/* Read the next bytes. */
if(ChkVal > 0)
{
if(Planes[j])
{
fread(Planes[j],ChkVal + 1,1,PicFile);
Planes[j] += ChkVal + 1;
}
else
fseek(PicFile,ChkVal + 1,1);
SoFar += ChkVal + 1;
}
else
{
/* Set the memory to this
* value.
*/
if(ChkVal != -128)
{
Value = fgetc(PicFile);
for(i = 0 ; i <= -ChkVal ; i++)
{
if(Planes[j])
{
*Planes[j] = Value;
Planes[j]++;
}
SoFar++;
}
}
}
}
}
}
}
/* Finish it up. */
Quit: fclose(PicFile);
return(TRUE);
}
/* FadeTo():
*
* Fades a palette into a different palette or colour.
*/
VOID
FadeTo(struct ViewPort *VPort,UWORD *From,UWORD *To,LONG NumColours,LONG ToCol,LONG FromCol)
{
UWORD FromTemp[32];
UWORD ToTemp[32];
SHORT i,j,R1,G1,B1,R2,G2,B2;
/* A bit too large? */
if(NumColours > 32)
NumColours = 32;
/* Do we have a source palette? */
if(From)
CopyMem(&From[0],&FromTemp[0],sizeof(UWORD) * 32);
else
memset(&FromTemp[0],FromCol,sizeof(UWORD) * 32);
/* Do we have a destination palette? */
if(To)
CopyMem(&To[0],&ToTemp[0],sizeof(UWORD) * 32);
else
memset(&ToTemp[0],ToCol,sizeof(UWORD) * 32);
/* Let's get into action. */
for(j = 0 ; j < 16 ; j++)
{
for(i = 0 ; i < NumColours ; i++)
{
/* Split the source colour. */
R1 = (FromTemp[i] >> 8) & 0xF;
G1 = (FromTemp[i] >> 4) & 0xF;
B1 = (FromTemp[i]) & 0xF;
/* Split the destination colour. */
R2 = (ToTemp[i] >> 8) & 0xF;
G2 = (ToTemp[i] >> 4) & 0xF;
B2 = (ToTemp[i]) & 0xF;
/* Adjust the colours. */
if(R1 > R2)
R1--;
if(G1 > G2)
G1--;
if(B1 > B2)
B1--;
/* Adjust the colours. */
if(R1 < R2)
R1++;
if(G1 < G2)
G1++;
if(B1 < B2)
B1++;
/* Put it together again. */
FromTemp[i] = (R1 << 8) | (G1 << 4) | B1;
}
/* Wait a bit. */
Delay(2);
/* Load the new map. */
LoadRGB4(VPort,FromTemp,NumColours);
}
}
/* InitTinyBitMap() :
*
* If the picture to be loaded is smaller than the
* screen it is to appear on, a custom bitmap is
* initialized to receive the image data.
*/
UBYTE
InitTinyBitMap()
{
SHORT i;
/* So the Blitter won't be confused. */
InitBitMap(&TinyBitMap,InfoHeader . nPlanes,InfoHeader . w,InfoHeader . h);
/* Try to steal some memory for the tiny bitmap. */
for(i = 0 ; i < InfoHeader . nPlanes ; i++)
if(!(TinyBitMap . Planes[i] = (PLANEPTR)AllocRaster(InfoHeader . w,InfoHeader . h)))
return(FALSE);
InitBitMap(&ScreenMap,InfoHeader . nPlanes,NewScreen . Width,NewScreen . Height);
/* Try to steal some memory for the bitplanes. */
for(i = 0 ; i < InfoHeader . nPlanes ; i++)
if(!(ScreenMap . Planes[i] = (PLANEPTR)AllocRaster(NewScreen . Width,NewScreen . Height)))
return(FALSE);
return(TRUE);
}
/* CleanExit() :
*
* Closes the libraries and exits.
*/
VOID
CleanExit(LONG ExitCode)
{
/* Take care of external signals. */
SetSignal(0,SIGBREAKF_CTRL_C);
/* Return the control to DOS. See what it's doing with
* it.
*/
exit(ExitCode);
}
/* CloseDisplay() :
*
* Closes anything that we have opened but the
* libraries.
*/
VOID
CloseDisplay()
{
SHORT i;
/* Canst thou hear me? Finish what you have started. */
ClearCycleCode();
/* A window! */
if(Window)
{
/* Hide the menu. */
Window -> Flags |= RMBTRAP;
/* We don't need the menu any more. */
ClearMenuStrip(Window);
CloseWindow(Window);
Window = NULL;
}
/* Is there a screen anywhere? */
if(Screen)
{
CloseScreen(Screen);
Screen = NULL;
}
/* Get rid of the planes. */
for(i = 0 ; i < ScreenMap . Depth ; i++)
{
if(TinyBitMap . Planes[i])
{
FreeRaster(TinyBitMap . Planes[i],InfoHeader . w,InfoHeader . h);
TinyBitMap . Planes[i] = NULL;
if(ScreenMap . Planes[i])
{
FreeRaster(ScreenMap . Planes[i],NewScreen . Width,NewScreen . Height);
ScreenMap . Planes[i] = NULL;
}
continue;
}
if(ScreenMap . Planes[i])
{
FreeRaster(ScreenMap . Planes[i],InfoHeader . w,InfoHeader . h);
ScreenMap . Planes[i] = NULL;
}
}
}
/* PrintScreen(Large):
*
* Sends the current LoadImage screen to the printer.
*/
VOID
PrintScreen(UBYTE Large)
{
struct IODRPReq *PrinterDump;
struct MsgPort *PrinterPort;
struct IntuiMessage *Massage;
ULONG Class;
USHORT Code;
UBYTE HasTitle = (Screen -> Flags & SHOWTITLE) ? TRUE : FALSE;
UBYTE Cycling = IsCycling();
LONG StartX,StartY,Width,Height;
volatile LONG OldX = -1,OldY = -1,TempX,TempY,X,Y;
SetSnooze(Window);
/* IO Replyport. */
if(PrinterPort = (struct MsgPort *)CreatePort(NULL,0))
{
/* Custom RastPort dump structure. */
if(PrinterDump = (struct IODRPReq *)CreateExtIO(PrinterPort,sizeof(struct IODRPReq)))
{
/* Try to open the device. */
if(!OpenDevice("printer.device",0,PrinterDump,0))
{
SetSize(Window);
SetDrMd(Window -> RPort,COMPLEMENT);
/* Don't let anyone disturb the
* LoadImage screen bitmap.
*/
Window -> Flags |= RMBTRAP;
if(HasTitle)
ShowTitle(Screen,FALSE);
if(Cycling)
ToggleCycleCode();
/* Let the user set the initial
* point.
*/
FOREVER
{
WaitPort(Window -> UserPort);
if(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort))
{
Class = Massage -> Class;
Code = Massage -> Code;
ReplyMsg(Massage);
}
if((Class == MOUSEBUTTONS && Code == MENUDOWN) || Class == RAWKEY)
{
DisplayBeep(Screen);
goto HitAndQuit;
}
if(Class == MOUSEBUTTONS && Code == SELECTDOWN)
{
X = Window -> MouseX;
Y = Window -> MouseY;
break;
}
}
/* Now let him resize the rubber box
* to the right dimensions.
*/
ReportMouse(TRUE,Window);
FOREVER
{
USHORT Qualifier;
TempX = Window -> MouseX;
TempY = Window -> MouseY;
if(TempX < 0)
TempX = 0;
if(TempY < 0)
TempY = 0;
if(TempX > Window -> Width - 1)
TempX = Window -> Width - 1;
if(OldX >= 0 && OldY >= 0)
{
Move(Window -> RPort,X,Y);
Draw(Window -> RPort,OldX,Y);
Draw(Window -> RPort,OldX,OldY);
Draw(Window -> RPort,X,OldY);
Draw(Window -> RPort,X,(OldY >= Y) ? Y + 1 : Y - 1);
}
else
OldX = OldY = 0;
Move(Window -> RPort,X,Y);
Draw(Window -> RPort,TempX,Y);
Draw(Window -> RPort,TempX,TempY);
Draw(Window -> RPort,X,TempY);
Draw(Window -> RPort,X,(TempY >= Y) ? Y + 1 : Y - 1);
OldX = TempX;
OldY = TempY;
WaitLoop: WaitPort(Window -> UserPort);
if(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort))
{
Class = Massage -> Class;
Code = Massage -> Code;
Qualifier = Massage -> Qualifier;
ReplyMsg(Massage);
}
if((Class == MOUSEBUTTONS && Code == MENUDOWN) || Class == RAWKEY)
{
DisplayBeep(Screen);
Move(Window -> RPort,X,Y);
Draw(Window -> RPort,TempX,Y);
Draw(Window -> RPort,TempX,TempY);
Draw(Window -> RPort,X,TempY);
Draw(Window -> RPort,X,(TempY >= Y) ? Y + 1 : Y - 1);
goto HitAndQuit;
}
if(Class == MOUSEBUTTONS && Code == SELECTUP)
{
Move(Window -> RPort,X,Y);
Draw(Window -> RPort,TempX,Y);
Draw(Window -> RPort,TempX,TempY);
Draw(Window -> RPort,X,TempY);
Draw(Window -> RPort,X,(TempY >= Y) ? Y + 1 : Y - 1);
StartX = (X < TempX) ? X : TempX;
StartY = (Y < TempY) ? Y : TempY;
Width = ABS(TempX - X) + 1;
Height = ABS(TempY - Y) + 1;
if(Width < 2 || Height < 2)
goto HitAndQuit;
break;
}
}
/* Initialize the IO Request for
* a RastPort dump.
*/
PrinterDump -> io_Command = PRD_DUMPRPORT;
PrinterDump -> io_RastPort = &Screen -> RastPort;
PrinterDump -> io_ColorMap = Screen -> ViewPort . ColorMap;
PrinterDump -> io_Modes = Screen -> ViewPort . Modes;
PrinterDump -> io_SrcWidth = Width;
PrinterDump -> io_SrcHeight = Height;
PrinterDump -> io_SrcX = StartX;
PrinterDump -> io_SrcY = StartY;
/* Print it as large as possible? */
if(Large)
{
PrinterDump -> io_DestCols = 0;
PrinterDump -> io_Special = SPECIAL_FULLCOLS | SPECIAL_ASPECT;
}
else
{
PrinterDump -> io_DestCols = Width;
PrinterDump -> io_Special = SPECIAL_MILCOLS | SPECIAL_ASPECT;
}
SetSnooze(Window);
/* Try the dump. */
if(DoIO(PrinterDump))
DisplayBeep(Screen);
/* Re-enable the window. */
HitAndQuit: Window -> Flags &= ~RMBTRAP;
SetPoint(Window);
/* If set, re-enable the screen title. */
if(HasTitle)
ShowTitle(Screen,TRUE);
if(Cycling)
ToggleCycleCode();
ReportMouse(FALSE,Window);
CloseDevice(PrinterDump);
}
else
DisplayBeep(Screen);
DeleteExtIO(PrinterDump);
}
else
DisplayBeep(Screen);
DeletePort(PrinterPort);
}
else
DisplayBeep(Screen);
SetPoint(Window);
}
/* GetRealName():
*
* Looks for a file and returns its real name.
*/
VOID
GetRealName(char *FullName,char *RealName)
{
struct FileInfoBlock *FileInfo;
BPTR FileLock;
if(FileLock = Lock(FullName,ACCESS_READ))
{
if(FileInfo = (struct FileInfoBlock *)AllocMem(sizeof(struct FileInfoBlock),MEMF_PUBLIC))
{
if(Examine(FileLock,FileInfo))
strcpy(RealName,FileInfo -> fib_FileName);
FreeMem(FileInfo,sizeof(struct FileInfoBlock));
}
UnLock(FileLock);
}
}
/* LoadImage():
*
* Will finally load and display an image file.
*/
LONG
LoadImage(char *FileName,UBYTE ForceScroll,UBYTE ForceLace,UBYTE CycleOnStartup,UBYTE LastOne)
{
UWORD Colours[32]; /* Colour buffer (yes I'm British!) */
LONG ViewModes;
WORD ColourNumber; /* Number of colours. */
SHORT MaxOffsetX,MaxOffsetY; /* Some scrolling stuff. */
volatile SHORT StartOffsetX,StartOffsetY;
SHORT Width,Height; /* Size of the ViewPort */
SHORT JumpY = 1,JumpX = 1; /* Scrolljump steps */
UBYTE WeAreScrolling = FALSE;
UBYTE RemakeTheView;
USHORT MenuNum;
struct MenuItem *Item;
UBYTE IsMouse; /* Scrollmode. */
UBYTE WasCycling; /* What happened? */
UBYTE ChangedColours = FALSE;
UBYTE IsTiny = FALSE; /* Image smaller than screen? */
LONG TinyX,TinyY; /* Image offsets for tiny bitmap. */
struct IntuiMessage *Massage;
ULONG Class;
USHORT Code;
SHORT i; /* Loop counters. */
volatile UBYTE *RightMouse = (UBYTE *)0xDFF016;
char RealName[108];
GetRealName(FileName,RealName);
/* Is it the last picture? */
if(LastOne)
MenuItem[8] . Flags &= ~ITEMENABLED;
else
MenuItem[8] . Flags |= ITEMENABLED;
/* Try to load the header. */
if((ViewModes = LoadHeader(FileName,&InfoHeader)) == -1)
return(ERR_NOIFF);
/* Are there any colours out there? */
if(!(ColourNumber = LoadCMAP(FileName,Colours,32,&InfoHeader)))
return(ERR_NOCOLMAP);
/* Take care of the size of the ViewPort. */
Width = InfoHeader . pageWidth;
Height = InfoHeader . pageHeight;
/* Forced scrolling? */
if(ForceScroll)
ViewModes &= ~(HIRES | LACE);
/* Forced interlaced display mode? */
if(ForceLace)
ViewModes |= LACE;
/* Take care of exotic screen sizes. */
if(InfoHeader . h > Height)
Height = InfoHeader . h;
if(InfoHeader . w > Width)
Width = InfoHeader . w;
/* Hires or lores? */
if(ViewModes & HIRES)
{
Width = 640;
JumpX = 2;
}
else
Width = 320;
/* Interlaced or not? This may get funny since
* it is possible to scroll the image in steps
* of one pixel. In doing so one copper list
* (either shortframe or longframe) is ignored
* and only half of the image is displayed
* correctly. To avoid this the scroll jump
* is set to two pixels.
*/
if(ViewModes & LACE)
JumpY = 2;
if(Height > GfxBase -> NormalDisplayRows * JumpY)
Height = GfxBase -> NormalDisplayRows * JumpY;
/* Adjust the information. */
NewScreen . Width = Width;
NewScreen . Height = Height;
NewScreen . Depth = InfoHeader . nPlanes;
NewScreen . ViewModes = ViewModes;
/* And don't forget the window. */
NewWindow . Width = Width;
NewWindow . Height = Height;
/* Anything wrong with the picture? */
if(InfoHeader . w < InfoHeader . pageWidth || InfoHeader . h < InfoHeader . pageHeight)
{
if(!InitTinyBitMap())
return(ERR_NOMEM);
IsTiny = TRUE;
}
else
{
/* Initialize the bitmap for future use. */
InitBitMap(&ScreenMap,InfoHeader . nPlanes,InfoHeader . w,InfoHeader . h);
/* Try to steal some memory for the bitplanes. */
for(i = 0 ; i < InfoHeader . nPlanes ; i++)
{
if(!(ScreenMap . Planes[i] = (PLANEPTR)AllocRaster(InfoHeader . w,InfoHeader . h)))
return(ERR_NOMEM);
IsTiny = FALSE;
}
}
/* Open the screen. */
if(!(Screen = (struct Screen *)OpenScreen(&NewScreen)))
return(ERR_NOMEM);
/* Hide the title bar and prepare the window. */
ShowTitle(Screen,FALSE);
NewWindow . Screen = Screen;
/* Try to open the window. */
if(!(Window = (struct Window *)OpenWindow(&NewWindow)))
return(ERR_NOMEM);
SetSnooze(Window);
SetWindowTitles(Window,(STRPTR)-1,(STRPTR)RealName);
/* Set up the alternate colour palette. */
for(i = 0 ; i < 32 ; i++)
{
PrefColours[i] = Colours[i];
if(i >= (1 << NewScreen . Depth))
PrefColours[i] = Colours[i] = GetRGB4(Screen -> ViewPort . ColorMap,i);
}
PrefColours[0] = StandardPrefs . color0;
PrefColours[1] = StandardPrefs . color1;
PrefColours[2] = StandardPrefs . color2;
PrefColours[3] = StandardPrefs . color3;
/* Load the colours. */
LoadRGB4(&Screen -> ViewPort,Colours,ColourNumber);
/* Just in case we will have to restore it. */
StartOffsetX = Screen -> ViewPort . RasInfo -> RxOffset;
StartOffsetY = Screen -> ViewPort . RasInfo -> RyOffset;
/* Play it safe --- keep the maximum scroll offset
* in reasonable dimensions.
*/
if((MaxOffsetX = InfoHeader . w - Width) < 0)
MaxOffsetX = 0;
if((MaxOffsetY = InfoHeader . h - Height) < 0)
MaxOffsetY = 0;
/* Absolute maximum limit. */
MaxOffsetX += StartOffsetX;
MaxOffsetY += StartOffsetY;
/* "Here comes the sun..." */
if(IsTiny)
{
if(!LoadRaster(FileName,TinyBitMap . Planes,&InfoHeader))
return(ERR_DOS);
}
else
{
if(!LoadRaster(FileName,ScreenMap . Planes,&InfoHeader))
return(ERR_DOS);
}
/* Do we allow colour cycling? */
if(LoadCycleRange(FileName,CycleRange,6))
InitCycleCode(&Screen -> ViewPort,Colours,ColourNumber,CycleRange,6);
/* Install the menu and the pointer. */
SetMenuStrip(Window,&Menu);
SetPoint(Window);
/* And - if necessary - print the tiny image. */
if(IsTiny)
{
if(InfoHeader . x + InfoHeader . w <= Screen -> Width)
TinyX = InfoHeader . x;
else
TinyX = (NewScreen . Width - InfoHeader . w) >> 1;
if(InfoHeader . y + InfoHeader . h <= Screen -> Height)
TinyY = InfoHeader . y;
else
TinyY = (NewScreen . Height - InfoHeader . h) >> 1;
BltBitMap(&TinyBitMap,0,0,Screen -> RastPort . BitMap,TinyX,TinyY,InfoHeader . w,InfoHeader . h,0xC0,0xFF,NULL);
}
/* Paint the screen black (for the effect). */
if(!(ViewModes & HAM))
LoadRGB4(&Screen -> ViewPort,BlackIsBlack,ColourNumber);
/* Bring the screen to the front. */
ScreenToFront(Screen);
ActivateWindow(Window);
FreeSprite(0);
/* Fade the colours in. */
if(!(ViewModes & HAM))
FadeTo(&Screen -> ViewPort,NULL,Colours,ColourNumber,0,0);
/* Allow the menu to be selected. */
Window -> Flags &= ~RMBTRAP;
/* If we are to cycle... */
if(CycleOnStartup)
ToggleCycleCode();
/* "Ewig währt am längsten." : Kurt Schwitters (1887 - 1948).
*
* Kurt Schwitters was a famous
* Hanoverian Dada artist.
*/
FOREVER
{
/* Let's be nice and wait for reactions. */
WaitPort(Window -> UserPort);
/* Massage the userport. */
if(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort))
{
Class = Massage -> Class;
Code = Massage -> Code;
/* If the user presses the menu button
* the menu appears. There is nothing
* wrong with this, but it might be
* possible that the user does not
* see the menu because of the raster
* offset. So we reposition the ViewPort
* before Intuition renders the menu bar.
* To keep the menu visible we adjust
* the colours if the right mouse
* button is pressed. This is done
* because of the fact that the
* keyboard shortcuts generate the
* same MENUVERIFY event. If there is
* anyone who doesn't like it this
* way he can try to test the keyboard
* matrix by tickling the hardware.
* I have chosen the easier way.
*/
if(Class == MENUVERIFY && !(*RightMouse & 4))
{
if(WasCycling = IsCycling())
ToggleCycleCode();
LoadRGB4(&Screen -> ViewPort,PrefColours,32);
ChangedColours = TRUE;
/* Reset the offsets. */
Screen -> ViewPort . RasInfo -> RxOffset = StartOffsetX;
Screen -> ViewPort . RasInfo -> RyOffset = StartOffsetY;
/* Remake the copper list. */
MakeScreen(Screen);
RethinkDisplay();
}
ReplyMsg(Massage);
}
/* If the user presses the select button
* we'll assume that he wants to scroll
* around in the picture.
*/
if(Class == MOUSEBUTTONS && Code == SELECTDOWN)
{
FreeSprite(0);
if(ChangedColours)
{
LoadRGB4(&Screen -> ViewPort,Colours,ColourNumber);
ChangedColours = FALSE;
if(WasCycling)
ToggleCycleCode();
WasCycling = FALSE;
}
WeAreScrolling = TRUE;
IsMouse = TRUE;
}
/* User pressed the cursor keys and wants
* to scroll around in the picture.
*/
if(Class == RAWKEY && (Code & ~IECODE_UP_PREFIX) >= CURSORUP && (Code & ~IECODE_UP_PREFIX) <= CURSORLEFT)
{
FreeSprite(0);
WeAreScrolling = TRUE;
IsMouse = FALSE;
}
/* User didn't like the menu shortcut
* and pressed the Tab key (is he a
* DPaint fanatic?).
*/
if(Class == RAWKEY && Code == 0x42)
{
FreeSprite(0);
ToggleCycleCode();
}
/* The user picked a menu item. */
if(Class == MENUPICK)
{
if(ChangedColours)
{
LoadRGB4(&Screen -> ViewPort,Colours,ColourNumber);
if(WasCycling)
ToggleCycleCode();
ChangedColours = FALSE;
WasCycling = FALSE;
}
MenuNum = Code;
/* Until the last event is traced. */
while(MenuNum != MENUNULL)
{
if(MENUNUM(MenuNum) == 0)
{
switch(ITEMNUM(MenuNum))
{
/* About... */
case 0: if(WasCycling = IsCycling())
ToggleCycleCode();
LoadRGB4(&Screen -> ViewPort,PrefColours,32);
/* Reset the offsets. */
Screen -> ViewPort . RasInfo -> RxOffset = StartOffsetX;
Screen -> ViewPort . RasInfo -> RyOffset = StartOffsetY;
/* Remake the copper list. */
MakeScreen(Screen);
RethinkDisplay();
InitRequester(&Req);
Req . Width = 300;
Req . Height = 175;
Req . LeftEdge = (Window -> Width - Req . Width) / 2;
Req . TopEdge = (Window -> Height - Req . Height) / 2;
Req . BackFill = 1;
Req . Flags = NOISYREQ | SIMPLEREQ;
Req . ReqGadget = &ReqGad;
Req . ReqBorder = &ReqBrd[2];
Req . ReqText = &ReqIntTxt[1];
if(Request(&Req,Window))
{
FOREVER
{
WaitPort(Window -> UserPort);
while(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort))
{
Class = Massage -> Class;
ReplyMsg(Massage);
if(Class == GADGETUP || Class == RAWKEY)
{
EndRequest(&Req,Window);
goto EndReq;
}
}
}
}
EndReq: SetPoint(Window);
LoadRGB4(&Screen -> ViewPort,Colours,ColourNumber);
if(WasCycling)
ToggleCycleCode();
FreeSprite(0);
break;
/* Toggle the presence of the screen title. */
case 2: FreeSprite(0);
if(Screen -> Flags & SHOWTITLE)
ShowTitle(Screen,FALSE);
else
ShowTitle(Screen,TRUE);
break;
/* Toggle cycling. */
case 3: FreeSprite(0);
ToggleCycleCode();
break;
/* Print screen (standard size). */
case 5: Screen -> ViewPort . RasInfo -> RxOffset = StartOffsetX;
Screen -> ViewPort . RasInfo -> RyOffset = StartOffsetY;
/* Remake the copper list. */
MakeScreen(Screen);
RethinkDisplay();
PrintScreen(FALSE);
break;
/* Print screen (enlarged). */
case 6: Screen -> ViewPort . RasInfo -> RxOffset = StartOffsetX;
Screen -> ViewPort . RasInfo -> RyOffset = StartOffsetY;
/* Remake the copper list. */
MakeScreen(Screen);
RethinkDisplay();
PrintScreen(TRUE);
break;
/* Next picture. */
case 8: if(IsCycling())
ToggleCycleCode();
WasCycling = FALSE;
if(!(ViewModes & HAM))
FadeTo(&Screen -> ViewPort,Colours,NULL,ColourNumber,0,0);
ScreenToBack(Screen);
CloseDisplay();
return(0);
/* Quit LoadImage. */
case 9: if(IsCycling())
ToggleCycleCode();
WasCycling = FALSE;
if(!(ViewModes & HAM))
FadeTo(&Screen -> ViewPort,Colours,NULL,ColourNumber,0,0);
ScreenToBack(Screen);
CloseDisplay();
return(-1);
}
}
/* See if there is another
* menu item around.
*/
Item = (struct MenuItem *)ItemAddress(&Menu,MenuNum);
MenuNum = Item -> NextSelect;
}
}
/* No chance to scroll anywhere, so we'll block
* it.
*/
if(MaxOffsetX == StartOffsetX && MaxOffsetY == StartOffsetY)
WeAreScrolling = FALSE;
/* This loop will run until the select button
* or the cursor key is released.
*/
while(WeAreScrolling)
{
if(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort))
{
Class = Massage -> Class;
Code = Massage -> Code;
ReplyMsg(Massage);
}
/* User doesn't want to scroll anymore? */
if(Code & IECODE_UP_PREFIX)
{
FreeSprite(0);
WeAreScrolling = FALSE;
}
/* Nothing happened. */
RemakeTheView = FALSE;
/* Left border, scroll left. */
if(((Window -> MouseX == 0 && IsMouse) || (Code == CURSORLEFT && !IsMouse)) && (Screen -> ViewPort . RasInfo -> RxOffset - JumpX >= StartOffsetX))
{
Screen -> ViewPort . RasInfo -> RxOffset -= JumpX;
RemakeTheView = TRUE;
}
/* Top border, scroll up. */
if(((Window -> MouseY == 0 && IsMouse) || (Code == CURSORUP && !IsMouse)) && (Screen -> ViewPort . RasInfo -> RyOffset - JumpY >= StartOffsetY))
{
Screen -> ViewPort . RasInfo -> RyOffset -= JumpY;
RemakeTheView = TRUE;
}
/* Right border, scroll right. */
if(((Window -> MouseX == Window -> Width - 1 && IsMouse) || (Code == CURSORRIGHT && !IsMouse)) && (Screen -> ViewPort . RasInfo -> RxOffset + JumpX <= MaxOffsetX))
{
Screen -> ViewPort . RasInfo -> RxOffset += JumpX;
RemakeTheView = TRUE;
}
/* Bottom border, scroll down. */
if(((Window -> MouseY == Window -> Height - 1 && IsMouse) || (Code == CURSORDOWN && !IsMouse)) && (Screen -> ViewPort . RasInfo -> RyOffset + JumpY <= MaxOffsetY))
{
Screen -> ViewPort . RasInfo -> RyOffset += JumpY;
RemakeTheView = TRUE;
}
/* Are we to scroll the ViewPort? */
if(RemakeTheView)
{
MakeScreen(Screen);
RethinkDisplay();
}
}
}
}
/* QuickSort(av,n) :
*
* Quicksort routine borrowed from Steve Drew's revision
* of Matt Dillon's Shell. Please don't ask me how it
* works, I forgot it some moments after my Pascal teacher
* had explained it to me in detail.
*/
VOID
QuickSort(char **av,LONG n)
{
LONG b;
if(n > 0)
{
b = QSplit(av,n);
QuickSort(av,b);
QuickSort(av + b + 1,n - b - 1);
}
}
/* QSplit(av,n) :
*
* Quicksort subroutine to save stack space.
*/
LONG
QSplit(char **av,LONG n)
{
LONG i,b;
char *element,*scr;
element = av[0];
for(b = 0,i = 1 ; i < n ; i++)
{
if(Strcmp(av[i],element) < 0)
{
b++;
scr = av[i];
av[i] = av[b];
av[b] = scr;
}
}
scr = av[0];
av[0] = av[b];
av[b] = scr;
return(b);
}
/* Chk_Abort() :
*
* The system calls this during I/O. Returns 0 to tell
* it that there is no CTRL-C around.
*/
LONG Chk_Abort(VOID) { return(0); }
/* _wb_parse(CurrentProcess,WBMsg) :
*
* Modified Workbench tool parsing routine. This one
* always opens a standard output window if the program
* has been started from Workbench. Original version
* Copyright (C) 1986,1987 by Manx Software Systems, Inc.
*/
void
_wb_parse(struct Process *CurrentProcess,struct WBStartup *WBMsg)
{
struct FileHandle *FileHandlePtr; /* Window pointer. */
BPTR FileWindow; /* BCPL window pointer. */
static char WindowTitle[40 + 18]; /* Title buffer. */
SHORT i = 0,j = 0; /* Counters. */
if(WBMsg -> sm_NumArgs == 1)
return;
/* Set up the window title. */
strcpy(WindowTitle,"CON:0/11/640/80/");
/* Find the end of the window title string. */
while(WindowTitle[i])
i++;
/* Append the tool name. */
while((WindowTitle[i++] = WBMsg -> sm_ArgList -> wa_Name[j++]) && j != 40);
/* Window title null termination. */
WindowTitle[40 + 17] = 0;
/* Open the window. */
if(FileWindow = Open(WindowTitle, MODE_OLDFILE))
{
/* Convert BPTR to window pointer. */
FileHandlePtr = (struct FileHandle *)BADDR(FileWindow);
CurrentProcess -> pr_ConsoleTask = (APTR)FileHandlePtr -> fh_Type;
/* Set up console IO streams. */
CurrentProcess -> pr_CIS = FileWindow;
CurrentProcess -> pr_COS = Open("*", MODE_OLDFILE);
/* Setup for exit to close these if we succeeded. */
_devtab[0] . mode &= ~O_STDIO;
_devtab[1] . mode &= ~O_STDIO;
}
}
VOID
main(int argc,char **argv)
{
struct FileRequester *Request;
SHORT i,NumItems,Error;
char TempName[DSIZE * 10 + FCHARS];
/* Setup the standard colours for later use. */
GetPrefs(&StandardPrefs,sizeof(struct Preferences));
/* Workbench startup? */
if(!argc)
{
extern struct WBStartup *WBenchMsg;
struct WBArg *WArg;
char FullPath[DSIZE * 10];
/* Didn't select any project icons? */
if((NumItems = WBenchMsg -> sm_NumArgs - 1) < 1)
{
if(Request = ArpAllocFreq())
{
Request -> fr_Hail = "Select file to display";
FOREVER
{
if(FileRequest(Request))
{
strcpy(TempName,Request -> fr_Dir);
TackOn(TempName,Request -> fr_File);
if(LoadImage(TempName,FALSE,FALSE,FALSE,FALSE) > 0)
DisplayBeep(NULL);
}
else
break;
}
}
CleanExit(RETURN_OK);
}
/* Take the first argument. */
WArg = WBenchMsg -> sm_ArgList;
WArg++;
/* Scan the list... */
for(i = 0 ; i < NumItems ; i++)
{
/* Build image file name. */
PathName(WArg -> wa_Lock,FullPath,DSIZE * 10);
TackOn(FullPath,WArg -> wa_Name);
WArg++;
Printf("Picture \33[33mNº %03ld\33[31m, \33[1m\"%s\"\33[0m loading... ",i + 1,FullPath);
if((Error = LoadImage(FullPath,FALSE,FALSE,TRUE,(i == NumItems - 1))) < 0 || BreakCheck())
{
if(BreakCheck())
Puts("*** aborted.\a");
else
Puts("");
break;
}
switch(Error)
{
case ERR_NOIFF: Printf("\33[33mNot an IFF-ILBM file.\33[31m\a");
break;
case ERR_NOCOLMAP: Printf("\33[33mNo colour map.\33[31m\a");
break;
case ERR_NOMEM: Printf("\33[33mNot enough memory.\33[31m\a");
break;
case ERR_DOS: Printf("\33[33mError while reading.\33[31m\a");
break;
default: Printf("Done.");
break;
}
Puts("");
}
Printf("\nPlease press \33[1mRETURN\33[0m.");
Read(Input(),FullPath,1);
CleanExit(RETURN_OK);
}
else
{
UBYTE ForceScroll = FALSE,ForceLace = FALSE,Cycle = FALSE;
SHORT Offset = 1,NumFiles,j;
char *FileArray[256],*Pat;
/* User wants information? */
if(argv[ARG_INFO])
{
Printf("\n \33[1m\33[33mLoadImage\33[31m\33[0m © Copyright 1990 by MXM\n\n");
Printf(" Usage is: \33[1mLoadImage\33[0m [INFO] [NOMODE]/[LACE] [CYCLE] Files1 ... FileN\n");
Printf(" \33[33mAmigaDOS\33[31m wildcards are supported!\n\n");
Printf(" \33[1mINFO\33[0m \33[33m»\33[31m Displays this page.\n");
Printf(" \33[1mNOMODE\33[0m \33[33m»\33[31m Force scrollmode (ignore Hi-Res & Interlace flags).\n");
Printf(" \33[1mLACE\33[0m \33[33m»\33[31m Force interlaced display mode.\n");
Printf(" \33[1mCYCLE\33[0m \33[33m»\33[31m Force colour cycling on startup.\n\n");
Printf(" Note that \33[1mNOMODE\33[0m and \33[1mLACE\33[0m are \33[4mmutually exclusive\33[0m.\n\n");
Printf(" If you wish to come in contact with \33[1mme\33[0m, here's my address:\n\n");
Printf("\tOlaf 'Olsen' Barthel\n");
Printf("\tBrabeckstrasse 35\n");
Printf("\tD-3000 Hannover 71\n\n");
Printf("\t\33[1mFederal Republic of Germany\33[0m\n\n");
Printf(" Have \33[4mfun\33[0m with the code ... \33[3mOlsen\33[0m\n\n");
CleanExit(0);
}
/* Both modes selected? */
if(argv[ARG_NOMODE] && argv[ARG_LACE])
{
Puts(CLI_Help);
CleanExit(RETURN_WARN);
}
/* Force scrolling? */
if(argv[ARG_NOMODE])
{
ForceScroll = TRUE;
Offset++;
}
/* Interlaced display mode? */
if(argv[ARG_LACE])
{
ForceLace = TRUE;
Offset++;
}
/* Cycle on startup? */
if(argv[ARG_CYCLE])
{
Cycle = TRUE;
Offset++;
}
/* No file names given? Show the file requester. */
if(!argv[ARG_FILES])
{
if(Request = ArpAllocFreq())
{
Request -> fr_Hail = "Select file to display";
FOREVER
{
if(FileRequest(Request))
{
strcpy(TempName,Request -> fr_Dir);
TackOn(TempName,Request -> fr_File);
if((Error = LoadImage(TempName,ForceScroll,ForceLace,Cycle,FALSE)) < 0 || BreakCheck())
{
if(BreakCheck())
Puts("*** aborted.\a");
else
Puts("");
break;
}
switch(Error)
{
case ERR_NOIFF: Printf("\33[33mNot an IFF-ILBM file.\33[31m\a");
break;
case ERR_NOCOLMAP: Printf("\33[33mNo colour map.\33[31m\a");
break;
case ERR_NOMEM: Printf("\33[33mNot enough memory.\33[31m\a");
break;
case ERR_DOS: Printf("\33[33mError while reading.\33[31m\a");
break;
default: Printf("Done.");
break;
}
Puts("");
}
}
}
CleanExit(RETURN_OK);
}
NumItems = argc - Offset;
/* Scan the argument list. */
for(i = 0 ; i < NumItems ; i++)
{
if(PreParse(argv[ARG_FILES + i],TempName))
{
NumFiles = 0;
while((Pat = scdir(argv[ARG_FILES + i])) && NumFiles < 255)
{
if(!(FileArray[NumFiles] = (char *)malloc(strlen(Pat) + 1)))
break;
strcpy(FileArray[NumFiles++],Pat);
if(NumFiles == 2)
Printf("\n\33[3mScanning directory for \33[0m\33[1m%s\33[0m...\n\n",BaseName(argv[ARG_FILES + i]));
}
if(NumFiles > 1)
QuickSort(FileArray,NumFiles);
for(j = 0 ; j < NumFiles ; j++)
{
if(!FileArray[j] || !FileArray[j][0])
continue;
Printf("Picture \33[33mNº %03ld\33[31m, \33[1m\"%s\"\33[0m loading... ",j + 1,BaseName(FileArray[j]));
if((Error = LoadImage(FileArray[j],ForceScroll,ForceLace,Cycle,(i == NumFiles - 1))) < 0 || BreakCheck())
{
if(BreakCheck())
Puts("*** aborted.\a");
else
Puts("");
break;
}
switch(Error)
{
case ERR_NOIFF: Printf("\33[33mNot an IFF-ILBM file.\33[31m\a");
break;
case ERR_NOCOLMAP: Printf("\33[33mNo colour map.\33[31m\a");
break;
case ERR_NOMEM: Printf("\33[33mNot enough memory.\33[31m\a");
break;
case ERR_DOS: Printf("\33[33mError while reading.\33[31m\a");
break;
default: Printf("Done.");
break;
}
Puts("");
}
for(j = 0 ; j < NumFiles ; j++)
free(FileArray[j]);
}
else
{
Printf("Picture \33[33mNº %03ld\33[31m, \33[1m\"%s\"\33[0m loading... ",i + 1,argv[ARG_FILES + i]);
if((Error = LoadImage(argv[ARG_FILES + i],ForceScroll,ForceLace,Cycle,(i == NumItems - 1))) < 0 || BreakCheck())
{
if(BreakCheck())
Puts("*** aborted.\a");
else
Puts("");
break;
}
switch(Error)
{
case ERR_NOIFF: Printf("\33[33mNot an IFF-ILBM file.\33[31m\a");
break;
case ERR_NOCOLMAP: Printf("\33[33mNo colour map.\33[31m\a");
break;
case ERR_NOMEM: Printf("\33[33mNot enough memory.\33[31m\a");
break;
case ERR_DOS: Printf("\33[33mError while reading.\33[31m\a");
break;
default: Printf("Done.");
break;
}
Puts("");
}
}
}
CleanExit(RETURN_OK);
}